/*
 * User: user
 * Date: 07/12/2007
 * Time: 23:34:54
 */
package org.conann.container;

import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkNotNull;
import com.google.common.collect.Iterables;
import org.conann.components.BeanImpl;
import org.conann.configuration.Configuration;
import org.conann.scan.ComponentScanner;
import static org.conann.util.DevelopmentUtil.unsupportedOperation;
import org.conann.util.ValidationUtil;

import javax.webbeans.Bean;
import javax.webbeans.Manager;
import javax.webbeans.TypeLiteral;
import java.lang.annotation.Annotation;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;

public class ManagerImpl implements Manager {

    private final BeanResolver beanResolver;
    private final Configuration configuration;

    public ManagerImpl(Configuration configuration) {
        this.configuration = configuration;
        BeansRegistry beansRegistry = new BeansRegistry(configuration);
        beanResolver = new BeanResolver(configuration, beansRegistry);
    }

    public void scanForcomponents() {
        ComponentScanner scanner = new ComponentScanner(configuration);
        scanner.scanSimpleComponents();
    }

    public <T> T getInstanceByType(Class<T> type, Annotation... bindingTypes) {
        checkNotNull(type);
        Set<Bean<T>> beans = resolveByType(type, bindingTypes);
        ValidationUtil.checkHasOneElement(beans, "beans");
        Bean<T> bean = Iterables.getOnlyElement(beans);
        return getInstance(bean);
    }

    private <T> T getInstance(Bean<T> bean) {
        Creator<T> creator = ((BeanImpl) bean).getCreator();
        return creator.create(bean, resolveInstrantiationParams());
    }

    private List<Object> resolveInstrantiationParams() {
        // TODO ophir >> get constructor parameters
        return new ArrayList<Object>();
    }

    public <T> T getInstanceByType(final TypeLiteral<T> type, final Annotation... bindingTypes) {
        checkNotNull(type);
        throw unsupportedOperation();
    }

    public <T> Set<Bean<T>> resolveByType(final Class<T> apiType, final Annotation... bindingTypes) {
        checkNotNull(apiType);
        Set<Bean<T>> possibleTypes = beanResolver.resolveByType(apiType, bindingTypes);
        ValidationUtil.checkHasOneElement(possibleTypes, "complying types");
        return possibleTypes;
    }

    public <T> Set<Bean<T>> resolveByType(final TypeLiteral<T> apiType, final Annotation... bindingTypes) {
        checkNotNull(apiType);
        throw unsupportedOperation();
    }

    public Object getInstanceByName(String name) {
        checkNotNull(name);
        checkArgument(name.trim().length() > 0);
        throw unsupportedOperation();
    }

    public <T> Set<Bean<T>> resolveByName(String name) {
        checkNotNull(name);
        checkArgument(name.trim().length() > 0);
        throw unsupportedOperation();
    }
}